package com.e0box.game.utils
{
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.events.TouchEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import com.e0box.game.event.InputEvent;

	[Event(name="onClick", type="com.e0box.game.event.InputEvent")]
	[Event(name="onPress", type="com.e0box.game.event.InputEvent")]
	[Event(name="onMove", type="com.e0box.game.event.InputEvent")]
	[Event(name="onRelease", type="com.e0box.game.event.InputEvent")]
	[Event(name="onResize", type="com.e0box.game.event.InputEvent")]
	[Event(name="onEnterFrame", type="com.e0box.game.event.InputEvent")]
	
	public class Input extends EventDispatcher
	{
		public static const CLICK_RANGE:Number = 10;
		
		private static var _stage:Stage;
		
		private static var _instance:Input
		
		private var _evt:InputEvent;
		
		private var _stageBounds:Rectangle;
		
		private var _moveRange:Point;
		private var _clickFlag:Boolean;
		private var _isMouseDown:Boolean;
		public function Input(single:validate)
		{
			if(!single) throw new Error("Error:Please use the static class 'get instance'.");
		}
		
		
		public static function get instance():Input{
			if(!_instance) _instance = new Input(new validate());
			
			return _instance;
		}
		
		public function set stage(value:Stage):void{
			if(_stage){
				if(_stage == value){
					return;
				}else{
					removeListener();
				}
			}
			
			_stage = value;
			
			_stageBounds = new Rectangle(0, 0, _stage.fullScreenWidth, _stage.fullScreenHeight);
			
			addListener();
		}
		
		public function get stage():Stage{
			return _stage;
		}
		
		public function get stageBounds():Rectangle{
			return _stageBounds;
		}
		
		private function addListener():void{
			stage.addEventListener(TouchEvent.TOUCH_TAP, onTap);
			stage.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
			stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd);
			stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
			stage.addEventListener(TouchEvent.TOUCH_OUT, onTouchEnd);
			
			stage.addEventListener(MouseEvent.CLICK, onClick);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			stage.addEventListener(MouseEvent.ROLL_OUT, onMouseUp);
			
			stage.addEventListener(Event.RESIZE, onResize);
			stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		private function removeListener():void{
			stage.removeEventListener(TouchEvent.TOUCH_TAP, onTap);
			stage.removeEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
			stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd);
			stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
			stage.removeEventListener(TouchEvent.TOUCH_OUT, onTouchEnd);
			
			stage.removeEventListener(MouseEvent.CLICK, onClick);
			stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			stage.removeEventListener(MouseEvent.ROLL_OUT, onMouseUp);
			
			stage.removeEventListener(Event.RESIZE, onResize);
			stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		private function onTap(evt:TouchEvent):void{
			evt.stopImmediatePropagation();
			
			_evt = new InputEvent(InputEvent.ON_CLICK);
			_evt.position = new Point(evt.stageX, evt.stageY);
			_evt.isTouchEvent = true;
			_evt.touchSize = new Point(evt.sizeX, evt.sizeY);
			_evt.sourceEvent = evt;
			
			dispatchEvent(_evt);
		}
		private function onTouchBegin(evt:TouchEvent):void{
			evt.stopImmediatePropagation();
			
			_evt = new InputEvent(InputEvent.ON_PRESS);
			_evt.position = new Point(evt.stageX, evt.stageY);
			_evt.isTouchEvent = true;
			_evt.touchSize = new Point(evt.sizeX, evt.sizeY);
			_evt.sourceEvent = evt;
			
			dispatchEvent(_evt);
		}
		private function onTouchEnd(evt:TouchEvent):void{
			evt.stopImmediatePropagation();
			
			_evt = new InputEvent(InputEvent.ON_RELEASE);
			_evt.position = new Point(evt.stageX, evt.stageY);
			_evt.isTouchEvent = true;
			_evt.touchSize = new Point(evt.sizeX, evt.sizeY);
			_evt.sourceEvent = evt;
			
			dispatchEvent(_evt);
		}
		private function onTouchMove(evt:TouchEvent):void{
			evt.stopImmediatePropagation();
			
			_evt = new InputEvent(InputEvent.ON_MOVE);
			_evt.position = new Point(evt.stageX, evt.stageY);
			_evt.isTouchEvent = true;
			_evt.touchSize = new Point(evt.sizeX, evt.sizeY);
			_evt.sourceEvent = evt;
			
			dispatchEvent(_evt);
		}
		
		private function onClick(evt:MouseEvent):void{
			evt.stopImmediatePropagation();
			
			if(!_clickFlag) return;
			
			_evt = new InputEvent(InputEvent.ON_CLICK);
			_evt.position = new Point(evt.stageX, evt.stageY);
			_evt.isTouchEvent = false;
			_evt.sourceEvent = evt;
			
			dispatchEvent(_evt);
		}
		private function onMouseDown(evt:MouseEvent):void{
			evt.stopImmediatePropagation();
			
			_isMouseDown = true;
			
			_evt = new InputEvent(InputEvent.ON_PRESS);
			_evt.position = new Point(evt.stageX, evt.stageY);
			_evt.isTouchEvent = false;
			_evt.sourceEvent = evt;
			
			_moveRange = _evt.position.clone();
			_clickFlag = true;
			
			dispatchEvent(_evt);
		}
		private function onMouseUp(evt:MouseEvent):void{
			evt.stopImmediatePropagation();
			
			_isMouseDown = false;
			
			_evt = new InputEvent(InputEvent.ON_RELEASE);
			_evt.position = new Point(evt.stageX, evt.stageY);
			_evt.isTouchEvent = false;
			_evt.sourceEvent = evt;
			
			dispatchEvent(_evt);
		}
		private function onMouseMove(evt:MouseEvent):void{
			evt.stopImmediatePropagation();
			
			if(!_isMouseDown) return;
			
			_evt = new InputEvent(InputEvent.ON_MOVE);
			_evt.position = new Point(evt.stageX, evt.stageY);
			_evt.isTouchEvent = false;
			_evt.sourceEvent = evt;
			
			if(Point.distance(_evt.position,_moveRange) > CLICK_RANGE) _clickFlag = false;
			
			dispatchEvent(_evt);
		}
		
		private function onEnterFrame(event:Event):void
		{
			event.stopImmediatePropagation();
			
			_evt = new InputEvent(InputEvent.ON_ENTER_FRAME);
			_evt.sourceEvent = event;
			
			dispatchEvent(_evt);
		}
		
		private function onResize(event:Event):void
		{
			event.stopImmediatePropagation();
			
			_evt = new InputEvent(InputEvent.ON_RESIZE);
			_evt.sourceEvent = event;
			
			dispatchEvent(_evt);
		}
		
	}
}

class validate{
	public function validate(){
		
	}
}